/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       enum_map.h

	$Header: /game/enum_map.h $

	$NoKeywords: $

 ************************************************************************/

#ifndef ENUM_MAP_H_INCLUDED
#define ENUM_MAP_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#pragma warning( disable: 4786 )

#include <map>
#include <vector>
#include "string_insensitive_compare.h"
#include "string_pair.h"

// -----------------------------------------------------------------
// class which maps an enum to a set of strings.  Assumes valid range is >= 0, and that
// values are contiguous.
// -----------------------------------------------------------------
class t_enum_map_base
{
public:
	t_enum_map_base( t_string_pair const* pairs, int count, int max_value );
	t_enum_map_base( t_char_ptr_pair const* pairs, int count, int max_value );
	~t_enum_map_base();

protected:
	typedef std::map< std::string, int, t_string_insensitive_less> t_map;

	t_map					 m_map;
	std::vector<std::string> m_keywords;
};

// -----------------------------------------------------------------
// type-safe template
// -----------------------------------------------------------------
template <typename type>
class t_enum_map : public t_enum_map_base
{
public:
	t_enum_map( t_string_pair const* pairs, int count, type max_value,
		        type invalid_value = type(-1) );
	t_enum_map( t_char_ptr_pair const* pairs, int count, type max_value,
		        type invalid_value = type(-1) );

	bool find( std::string keyword, type& result ) const;

	const char* operator[]( type arg ) const;
	type        operator[]( std::string keyword ) const;
protected:
	type m_invalid_value;
};

// -----------------------------------------------------------------
// inlines for t_enum_map
// -----------------------------------------------------------------
template <typename type>
inline t_enum_map<type>::t_enum_map( t_string_pair const* pairs, int count, 
									 type max_value, type invalid_value )
					   : t_enum_map_base( pairs, count, max_value )
{
	m_invalid_value = invalid_value;
}

template <typename type>
inline t_enum_map<type>::t_enum_map( t_char_ptr_pair const* pairs, int count, 
									 type max_value, type invalid_value )
					   : t_enum_map_base( pairs, count, max_value )
{
	m_invalid_value = invalid_value;
}

template <typename type>
bool t_enum_map<type>::find( std::string keyword, type& result ) const
{
	t_map::const_iterator index = m_map.find( keyword );

	if (index == m_map.end())
		return false;
	result = type( index->second );
	return true;
}

template <typename type>
inline const char* t_enum_map<type>::operator[]( type arg ) const
{
	return m_keywords[arg].c_str();
}

template <typename type>
inline type t_enum_map<type>::operator[]( std::string keyword ) const
{
	type result;

	if (!find( keyword, result))
		return m_invalid_value;
	return result;
}

#endif // ENUM_MAP_H_INCLUDED